"""
车牌识别系统核心模块
整合车牌检测和识别功能，提供完整的车牌识别服务
"""

import cv2
import numpy as np
from typing import List, Dict, Optional, Tuple
from pathlib import Path
from src.config import config
from src.utils.logger import app_logger
from src.utils.image_utils import image_processor
from src.detection.plate_detector import plate_detector
from src.recognition.plate_recognizer import plate_recognizer


class LicensePlateSystem:
    """
    车牌识别系统核心类
    
    用途：
    - 整合车牌检测和识别功能
    - 提供完整的车牌识别流程
    - 支持单张图像和批量处理
    
    使用场景：
    - 交通监控系统
    - 停车场管理系统
    - 车辆出入管理
    """
    
    def __init__(self):
        """
        初始化车牌识别系统
        """
        self.detector = plate_detector
        self.recognizer = plate_recognizer
        self.output_dir = Path(config.get('paths.output_dir'))
        self.output_dir.mkdir(parents=True, exist_ok=True)
        
        app_logger.info("车牌识别系统初始化完成")
    
    def process_image(self, image_path: str, save_result: bool = False) -> Dict:
        """
        处理单张图像，完成车牌检测和识别
        
        参数：
            image_path (str): 图像文件路径
            save_result (bool): 是否保存结果图像
            
        返回值：
            Dict: 处理结果，包含：
                - success: 是否成功
                - detections: 检测结果列表
                - total_plates: 检测到的车牌数量
                - processing_time: 处理时间
                - result_image_path: 结果图像路径（如果保存）
        """
        start_time = cv2.getTickCount()
        
        try:
            # 加载图像
            image = image_processor.load_image(image_path)
            if image is None:
                return self._create_error_result("图像加载失败")
            
            # 检测车牌
            detections = self.detector.detect_plates(image)
            
            if not detections:
                app_logger.warning("未检测到车牌")
                return self._create_result([], 0, start_time)
            
            # 提取车牌图像
            plate_results = self.detector.extract_plate_images(image, detections)
            
            # 识别车牌文字
            recognition_results = []
            for plate_result in plate_results:
                plate_image = plate_result['plate_image']
                
                # 识别车牌文字
                recognition = self.recognizer.recognize_plate(plate_image)
                
                # 合并结果
                combined_result = {
                    **plate_result,
                    **recognition
                }
                
                recognition_results.append(combined_result)
            
            # 计算处理时间
            processing_time = (cv2.getTickCount() - start_time) / cv2.getTickFrequency()
            
            # 生成结果图像
            result_image = self._draw_detection_results(image, recognition_results)
            
            # 保存结果图像
            result_image_path = None
            if save_result:
                result_image_path = self._save_result_image(
                    result_image, recognition_results, image_path
                )
            
            result = {
                'success': True,
                'detections': recognition_results,
                'total_plates': len(recognition_results),
                'processing_time': processing_time,
                'result_image_path': result_image_path,
                'result_image': result_image,
                'image_path': image_path
            }
            
            app_logger.info(f"处理完成，检测到 {len(recognition_results)} 个车牌，用时 {processing_time:.2f}s")
            return result
            
        except Exception as e:
            app_logger.error(f"图像处理失败: {e}")
            return self._create_error_result(str(e))
    
    def process_image_array(self, image: np.ndarray, save_result: bool = False) -> Dict:
        """
        处理图像数组
        
        参数：
            image (np.ndarray): 图像数组
            save_result (bool): 是否保存结果图像
            
        返回值：
            Dict: 处理结果
        """
        start_time = cv2.getTickCount()
        
        try:
            # 检测车牌
            detections = self.detector.detect_plates(image)
            
            if not detections:
                return self._create_result([], 0, start_time)
            
            # 提取车牌图像
            plate_results = self.detector.extract_plate_images(image, detections)
            
            # 识别车牌文字
            recognition_results = []
            for plate_result in plate_results:
                plate_image = plate_result['plate_image']
                
                # 识别车牌文字
                recognition = self.recognizer.recognize_plate(plate_image)
                
                # 合并结果
                combined_result = {
                    **plate_result,
                    **recognition
                }
                
                recognition_results.append(combined_result)
            
            # 计算处理时间
            processing_time = (cv2.getTickCount() - start_time) / cv2.getTickFrequency()
            
            # 保存结果图像
            result_image_path = None
            if save_result:
                result_image_path = self._save_result_image(
                    image, recognition_results, "processed_image"
                )
            
            result = {
                'success': True,
                'detections': recognition_results,
                'total_plates': len(recognition_results),
                'processing_time': processing_time,
                'result_image_path': result_image_path
            }
            
            return result
            
        except Exception as e:
            app_logger.error(f"图像处理失败: {e}")
            return self._create_error_result(str(e))
    
    def process_batch(self, image_paths: List[str], save_results: bool = False) -> List[Dict]:
        """
        批量处理图像
        
        参数：
            image_paths (List[str]): 图像文件路径列表
            save_results (bool): 是否保存结果图像
            
        返回值：
            List[Dict]: 处理结果列表
        """
        results = []
        
        app_logger.info(f"开始批量处理 {len(image_paths)} 张图像")
        
        for i, image_path in enumerate(image_paths):
            app_logger.info(f"处理第 {i+1}/{len(image_paths)} 张图像: {image_path}")
            
            result = self.process_image(image_path, save_results)
            result['image_path'] = image_path
            results.append(result)
        
        # 统计结果
        total_plates = sum(r['total_plates'] for r in results)
        successful_images = sum(1 for r in results if r['success'])
        
        app_logger.info(f"批量处理完成，成功处理 {successful_images}/{len(image_paths)} 张图像，共检测到 {total_plates} 个车牌")
        
        return results
    
    def get_detection_statistics(self, results: List[Dict]) -> Dict:
        """
        获取检测统计信息
        
        参数：
            results (List[Dict]): 处理结果列表
            
        返回值：
            Dict: 统计信息
        """
        if not results:
            return {}
        
        total_images = len(results)
        successful_images = sum(1 for r in results if r['success'])
        total_plates = sum(r['total_plates'] for r in results)
        total_processing_time = sum(r.get('processing_time', 0) for r in results)
        
        # 统计有效车牌
        valid_plates = 0
        confidence_scores = []
        
        for result in results:
            if result['success']:
                for detection in result['detections']:
                    if detection.get('is_valid', False):
                        valid_plates += 1
                    confidence_scores.append(detection.get('confidence', 0))
        
        avg_confidence = np.mean(confidence_scores) if confidence_scores else 0
        avg_processing_time = total_processing_time / total_images if total_images > 0 else 0
        
        statistics = {
            'total_images': total_images,
            'successful_images': successful_images,
            'success_rate': successful_images / total_images if total_images > 0 else 0,
            'total_plates': total_plates,
            'valid_plates': valid_plates,
            'validity_rate': valid_plates / total_plates if total_plates > 0 else 0,
            'average_confidence': avg_confidence,
            'total_processing_time': total_processing_time,
            'average_processing_time': avg_processing_time
        }
        
        return statistics
    
    def _create_result(self, detections: List[Dict], total_plates: int, start_time: float) -> Dict:
        """
        创建处理结果
        
        参数：
            detections (List[Dict]): 检测结果
            total_plates (int): 车牌总数
            start_time (float): 开始时间
            
        返回值：
            Dict: 处理结果
        """
        processing_time = (cv2.getTickCount() - start_time) / cv2.getTickFrequency()
        
        return {
            'success': True,
            'detections': detections,
            'total_plates': total_plates,
            'processing_time': processing_time,
            'result_image_path': None
        }
    
    def _create_error_result(self, error_message: str) -> Dict:
        """
        创建错误结果
        
        参数：
            error_message (str): 错误信息
            
        返回值：
            Dict: 错误结果
        """
        return {
            'success': False,
            'error': error_message,
            'detections': [],
            'total_plates': 0,
            'processing_time': 0,
            'result_image_path': None
        }
    
    def _save_result_image(self, image: np.ndarray, detections: List[Dict], 
                          original_path: str) -> str:
        """
        保存结果图像
        
        参数：
            image (np.ndarray): 原始图像
            detections (List[Dict]): 检测结果
            original_path (str): 原始图像路径
            
        返回值：
            str: 保存的图像路径
        """
        try:
            # 在图像上绘制检测结果
            result_image = image_processor.draw_detection_results(image, detections)
            
            # 生成输出文件名
            original_name = Path(original_path).stem
            output_filename = f"{original_name}_result.jpg"
            output_path = self.output_dir / output_filename
            
            # 保存图像
            cv2.imwrite(str(output_path), result_image)
            
            app_logger.info(f"结果图像已保存: {output_path}")
            return str(output_path)
            
        except Exception as e:
            app_logger.error(f"保存结果图像失败: {e}")
            return None
    
    def update_confidence_threshold(self, threshold: float):
        """
        更新置信度阈值
        
        参数：
            threshold (float): 新的置信度阈值
        """
        self.detector.set_confidence_threshold(threshold)
        app_logger.info(f"置信度阈值已更新为: {threshold}")
    
    def _draw_detection_results(self, image: np.ndarray, detections: List[Dict]) -> np.ndarray:
        """
        在图像上绘制检测结果
        
        参数：
            image (np.ndarray): 原始图像
            detections (List[Dict]): 检测结果列表
            
        返回值：
            np.ndarray: 绘制了检测结果的图像
        """
        # 使用image_processor的draw_detection_results方法来正确显示中文
        return image_processor.draw_detection_results(image, detections)
    
    def get_system_info(self) -> Dict:
        """
        获取系统信息
        
        返回值：
            Dict: 系统信息
        """
        return {
            'detector_model': self.detector.model_path,
            'recognizer_languages': self.recognizer.languages,
            'confidence_threshold': self.detector.confidence_threshold,
            'iou_threshold': self.detector.iou_threshold,
            'output_directory': str(self.output_dir)
        }


# 全局车牌识别系统实例
license_plate_system = LicensePlateSystem() 